﻿using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;

namespace FTI
{
    public class Composition
    {
        private CompositionContainer _container;

        private Properties.Settings Settings { get { return Properties.Settings.Default; } }

        [Import("SystemEventLog", typeof(IEventLogging))]
        public IEventLogging Log { get; set; }

        public Composition()
        {
            ComposeContainer(this);
        }

        public bool ComposeContainer(object pObject, bool refresh = false)
        {
            if (_container == null || refresh)
            {
                AggregateCatalog oCatalog = new AggregateCatalog();

                if (Assembly.GetEntryAssembly() != null)
                {
                    oCatalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetEntryAssembly()));
                }

                string
                    oExtensionFolder = String.Format("{0}\\{1}", Environment.CurrentDirectory, Settings.ExtensionFolder);

                if (Directory.Exists(oExtensionFolder))
                {
                    oCatalog.Catalogs.Add(new ApplicationCatalog());

                    oCatalog.Catalogs.Add(new DirectoryCatalog(oExtensionFolder));
                }

                _container = new CompositionContainer(oCatalog);
            }

            try
            {
                _container.ComposeParts(pObject);
            }
            catch (CompositionException pEx)
            {
                // this is where we would have some kind of error tracking.
                // since composition failed we will log this issue straight to the system event log
                if (Log == null)
                {
                    EventLog oLogging = new EventLog("FTI Event Log")
                    {
                        Source = "FTI Event Log"
                    };

                    if (EventLog.SourceExists(oLogging.Source))
                    {
                        oLogging.WriteEntry(pEx.Message, EventLogEntryType.Error, 0, (short)SystemCategory.Composition, Encoding.UTF8.GetBytes(pEx.ToString()));
                    }
                    else
                    {
                        Trace.Write(pEx.Message, Enum.GetName(typeof(SystemCategory), SystemCategory.Composition));
                    }
                }
                else
                {
                    Log.Write(pEx.Message, EventLogEntryType.Error, SystemCategory.Composition, Encoding.UTF8.GetBytes(pEx.ToString()));
                }

                return false;
            }

            return true;
        }
    }
}
